package com.umiwe.gateway.filter;

import com.alibaba.fastjson.JSONObject;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.umiwe.entity.*;
import com.umiwe.gateway.feign.GatewayFeignClient;
import com.umiwe.gateway.common.Code;
import com.umiwe.gateway.common.ResponseMsg;
import com.umiwe.utils.JsonUtils;
import com.umiwe.utils.RedisUtil;
import com.umiwe.utils.Result;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 *  网关过滤器
 *  加入到Spring容器
 */
@Component
public class UserLoginZuulFilter<T> extends ZuulFilter {

    private static final Logger log = LoggerFactory.getLogger(UserLoginZuulFilter.class);

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private GatewayFeignClient gatewayFeignClient;

    @Override
    public boolean shouldFilter() {
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();
        String HeaderToken = request.getHeader("token");;
        Map<String,T> requestData = this.getRequestData(request);
        //查询是否过滤
        String stringUrl = (String)requestData.get("stringUrl");
        //查询是否需要过滤
        Result result = gatewayFeignClient.filterStatus(stringUrl);
        if(!(boolean)result.getData()){
            //判断url长度
            //判断 systemString 是否存在
            Result systemString = gatewayFeignClient.getServerName((String) requestData.get("systemString"));
            if(systemString.getCode() == 200 && systemString.getData() != null){
                Integer systemId = (Integer)systemString.getData();
                //判断用户有没有 这个系统的权限
                if(redisUtil.exists(HeaderToken)){
                    UmiweUser umiweUser = JsonUtils.jsonToPojo((String) redisUtil.get(HeaderToken), UmiweUser.class);
                    //查询用户对应的角色 1对多
                    Result UserRoleList = gatewayFeignClient.getUserRoleList(727);
                    List<Map> umiweRoles = JsonUtils.jsonToList((String) UserRoleList.getData(), Map.class);
                    if(umiweRoles.size() > 0){
                        Result userRole = gatewayFeignClient.getUserRole(727, systemId);
                        UserRoleVO userRoleVO = JsonUtils.jsonToPojo((String) userRole.getData(), UserRoleVO.class);
                        if(userRoleVO != null){
                            //根据角色id查询权限信息
                            Result rolePermissionById = gatewayFeignClient.getRolePermissionById(userRoleVO.getRoleId());
                            List<UmiweRolePermissionVO> umiweRolePermissionVOList = JsonUtils.jsonToList((String) rolePermissionById.getData(), UmiweRolePermissionVO.class);
                            //保存角色对系统的操作权限
                            redisUtil.hmSet((String) requestData.get("systemString"),userRoleVO.getRoleId(),JsonUtils.objectToJson(umiweRolePermissionVOList));
                            //保存用户有哪些角色
                            redisUtil.hmSet((String) requestData.get("systemString"),umiweUser.getId().intValue(),JsonUtils.objectToJson(umiweRoles));
                            return false;
                        }else{
                            setErrorResponse(requestContext,"用户没权限,请联系管理员配置");
                            return true;
                        }
                    }else{
                        setErrorResponse(requestContext,"暂无角色,请联系管理员配置");
                        return true;
                    }
                }else{
                    setErrorResponse(requestContext,"请重新登录");
                    return true;
                }
            }else{
                setErrorResponse(requestContext,"系统不存在，请联系管理员");
                return true;
            }
        }else{
            // 过滤
            return false;
        }
    }

    /**
     *
     * key直接是 {$token}=>  user_info
     * resource_{$system_id} =》系统菜单资源
     * system_role_{$system_id} =》系统所有的角色对应菜单资源（权限）
     * user_role_{$user_id} =》用户对应的 {系统=》角色}
     * user_token =>{$user_id}对应的{$token}
     *
     * @return
     */
    @Override
    public Object run() { //编写业务逻辑
       return null;
    }

    /**
     * 获取请求中验证权限必要的参数
     * @param request
     * @return
     */
    private Map<String,T> getRequestData(HttpServletRequest request){
        //创建一个map，用于存放参数
        Map<String,T> requestData = new HashMap<>();
        //添加token在map里
        requestData.put("token", (T) request.getHeader("x-csrf-token"));
        //requestData.put("token",(T)111);
        //去除两边空白字符
        String url = request.getRequestURI().trim();
        //添加url在map里
        requestData.put("url", (T) url);
        //去除首尾指定字符
        url = trimFirstAndLastChar(url, "/");
        //通过/进行截取拆分
        String[] urlArr = url.split("/");
        //添加系统名称在map里
        requestData.put("systemString", (T) urlArr[0]);
        //使用复制方法进行（删除第一个数组元素）
        String[] urlArrNew = Arrays.copyOfRange(urlArr, 1, urlArr.length);
        //数组转化为字符串(斜杠分隔)
        String stringUrl = StringUtils.join(urlArrNew,"/");
        //添加加工过后的系统Url到map里
        requestData.put("stringUrl", (T) stringUrl);
        //返回map数据
        return requestData;
    }

    public void setErrorResponse(RequestContext requestContext, String msg) {
        requestContext.setSendZuulResponse(false);
        requestContext.setResponseStatusCode(401);
        String responseMsg = JSONObject.toJSONString(new ResponseMsg(Code.FAIL,"", msg));
        requestContext.setResponseBody(responseMsg);
        requestContext.getResponse().setContentType("text/json;charset=UTF-8");
    }


    @Override
    public String filterType() {
        // 设置过滤器类型为：pre
        return FilterConstants.PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        // 设置执行顺序为0
        return 0;
    }

    /**
     * 去除首尾指定字符
     * @param str 字符串
     * @param element 指定字符
     * @return
     */
    public String trimFirstAndLastChar(String str, String element){
        boolean beginIndexFlag = true;
        boolean endIndexFlag = true;
        do{
            int beginIndex = str.indexOf(element) == 0 ? 1 : 0;
            int endIndex = str.lastIndexOf(element) + 1 == str.length() ? str.lastIndexOf(element) : str.length();
            str = str.substring(beginIndex, endIndex);
            beginIndexFlag = (str.indexOf(element) == 0);
            endIndexFlag = (str.lastIndexOf(element) + 1 == str.length());
        } while (beginIndexFlag || endIndexFlag);
        return str;
    }

    public String getResourcesPath(String url) {
        String[] arr = url.split("/");
        String[] temp = new String[arr.length - 1];
        System.arraycopy(arr, 1, temp, 0, temp.length);
        StringBuilder resources = new StringBuilder();
        for (int i = 0; i < temp.length; i++) {
            if (i == temp.length -1) {
                resources.append(temp[i]);
            } else {
                resources.append(temp[i]).append("/");
            }
        }
        String getResourcesPath = resources.toString();
        return getResourcesPath;
    }
}
